#include "string.h"
struct String::Srep
{
    char* s; //points to elements
    int sz;  //number of characters
    int n;   //reference count
    Srep(int nsz, const char* p){
        n = 1;
        sz = nsz;
        s = new char[sz+1];
        strcpy(s, p);
    }
    ~Srep(){
        delete[] s;
    }
    Srep* get_own_copy(){//clone if necessary
        if( n==1) return this;
        n--;
        return new Srep(sz,s);
    }
    void assign(int nsz, const char* p){
        if(sz != nsz){
            delete[] s;
            sz = nsz;
            s = new char[sz+1];
        }
        strcpy(s,p);
    }
private:
    Srep(const Srep&);
    Srep& operator=(const Srep&);
};
//Constructor
String::String()
{
    _rep = new Srep(0,"");
}
String::String(const String& x)//copy constructor
{
    x._rep->n++;
    _rep = x._rep;
}
String::String(const char* s)//constructor
{
    _rep = new Srep(strlen(s), s);
}

String::~String()
{
    if(--_rep->n==0)delete _rep;
}
//copy assignment 1
String& String::operator=(const String& x)
{
    x._rep->n++;
    if(--_rep->n==0) delete _rep;
    _rep = x._rep;
    return *this;
}
//copy assignment 2
String&String::operator=(const char* s)
{
    if(_rep->n == 1)
        _rep->assign(strlen(s),s);
    else{
        _rep->n--;
        _rep = new Srep(strlen(s),s);
    }
    return *this;
}
void String::check(int i)const
{
    if( i<0 || _rep->sz <= i)throw Range();
}
char String::read(int i)const
{
    return _rep->s[i];
}
void String::write(int i, char c)
{
    _rep=_rep->get_own_copy();
    _rep->s[i]=c;
}

Cref String::operator[](int i)
{
    check(i);
    return Cref(*this,i);
}
char String::operator[](int i)const
{
    check(i);
    return _rep->s[i];
}
int String::size()const
{
    return _rep->sz;
}
const String String::operator()(int left, int right)const
{
    check(left);
    check(right);
    if(left <= right){
        char* buffer = new char[right-left+2];
        std::strncpy(buffer, _rep->s+left, right-left+1);
        buffer[right-left+1] = '\0';
        String result(buffer);
        delete[] buffer;
        return result;
    }
    else{
        return String("");
    }
}
const char* String::c_string()
{
    return _rep->s;
}

String_sub String::operator()(int left, int right)
{
    return String_sub(*this, left, right);
}

bool operator==(const String& x, const char* s)
{
    return strcmp(x._rep->s,s) == 0;
}
bool operator==(const String& x, const String& y)
{
    return strcmp(x._rep->s, y._rep->s)==0;
}
bool operator !=(const String& x,const char* s)
{
    return strcmp(x._rep->s,s) != 0;
}
bool operator!=(const String&x, const String& y)
{
    return strcmp(x._rep->s, y._rep->s) != 0;
}
String operator+(const String& left, const String& right)
{
    String ret;
    size_t length = strlen(left._rep->s) + strlen(right._rep->s);
    char* buffer = new char[length+1];
    strcpy(buffer,left._rep->s);
    strcpy(buffer + strlen(left._rep->s), right._rep->s);
    ret._rep->assign(length+1, buffer);
    return ret;
}
String operator+(const String&, const char*)
{
}
ostream& operator<<(ostream& os, const String& str)
{
    return os << str._rep->s;
}
istream& operator>>(istream& is, String& str)
{
    char buffer[1024];
    is >> buffer;
    str._rep->assign(strlen(buffer), buffer);
    return is;
}
String& String_sub::operator=(const char* s)
{
    assert(strlen(s) == _right - _left);
    strcpy(_str._rep->s + _left, s);
    return _str;
}
ostream& operator<<(ostream& os, const String_sub& sub)
{
    for(int i = sub._left; i < sub._right; i++)
        os << sub._str[i];
    return os;
}
    
    
